
#include  <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libgen.h>

#include <glib.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

#include "lmp-debug.h"

#include "totem-lrc-down.h"
//static void my_free(LyricId *item);
static GSList* tt_parse_lyricslist(gchar* xml);

char* tt_http_request(char* url)
{
//	lmp_debug("");
	int ret;
	char *fileBuf = NULL;				/* Pointer to downloaded data */

	ret = http_fetch(url, &fileBuf);	/* Downloads page */
//	lmp_debug("");
	if(ret == -1)						/* All HTTP Fetcher functions return */
	{
		http_perror("http_fetch");		/*	-1 on error. */
		return NULL;
	}
	
//	lmp_debug("");
	return fileBuf;
}

//g_free when no use again.
gchar* tt_encode_artist_title(const char* str)
{
	lmp_debug("");
	int i, j;
	char temp[64];

	assert(str != NULL);
	int str_len = strlen(str);
	int utf16_len = g_utf8_strlen(str, str_len) * 2;

//	lmp_debug("");
	char* re = g_new0(char, str_len * 6 + 1); //FIXME:这里应是多大才好呢？

//	lmp_debug("");
	gunichar2* utf16_str = g_utf8_to_utf16(str, 
			str_len,
			NULL,
			NULL,
			NULL);

//	lmp_debug("");
	char* p = (char*)utf16_str;

//	lmp_debug("str: %s", str);
	for(i = 0, j = 0; i < utf16_len; ++i)
	{
		sprintf(temp, "%02x", p[i]);
//		lmp_debug("i = %d, temp = %s", i, temp);
		int n = strlen(temp);
		re[j] = temp[n - 2];
		++j;
		re[j] = temp[n - 1];
		++j;
	}
	re[j] = '\0';

	lmp_debug("");
	g_free(utf16_str);
	return re;
}

//g_free when no use again.
static gchar* tt_remove_blankspace_lower(const gchar* src)
{
	lmp_debug("");

	gchar* s = NULL;
	int len = src?strlen(src):0;

	if(len == 0)
	{
		s = g_strdup("");
		return s;
	}

//	lmp_debug("g_new0 begin: len(src) = %d", len);

	s = g_new0(gchar, len + 1);

//	lmp_debug("g_new0 end");

	int i, j;
	for(i = 0, j = 0; i < len; ++i)
	{
		if(src[i] != ' ')
		{
			s[j] = g_ascii_tolower(src[i]);
			++j;
		}
	}
	s[j] = '\0';

	lmp_debug("");
	return s;
}

GSList* tt_get_lyrics_list(const gchar* artist, const gchar* title)
{
	lmp_debug("artist: %s, title: %s", artist, title);
//	assert(artist != NULL);
//	assert(title != NULL);
	if(!(artist||title))
		return NULL;
	gchar* art1 = tt_remove_blankspace_lower(artist);
	gchar* art2 = tt_encode_artist_title(art1);

//	lmp_debug("g_free(art1)");
	g_free(art1); //FIXME:

	gchar* tit1 = tt_remove_blankspace_lower(title);
	gchar* tit2 = tt_encode_artist_title(tit1);
	g_free(tit1); //FIXME:

	gchar* url = g_strdup_printf( 
			"http://lrcct2.ttplayer.com/dll/lyricsvr.dll?sh?Artist=%s&Title=%s&Flags=0",
			art2, tit2);

	printf("url: %s\n", url);

	g_free(art2); //FIXME:
	g_free(tit2); //FIXME:
	gchar* xml = tt_http_request(url);
//	lmp_debug("free url");
	g_free(url);

	GSList *l = tt_parse_lyricslist(xml);
	g_free(xml);

	return l;
}

gboolean tt_is_lrc_buf(gchar *buf)
{   ///use simple method to know is that a lyric buffer。
	gint i=0;
	if(!buf)
		return FALSE;
	while(*buf){
		if(*buf==':'||*buf=='['||*buf==']'){
			i++;
			if(*buf==']')break;
		}
	buf++;
	}
	return (i>=3);
}


gboolean tt_get_lyrics_content_save(gchar *url,gchar *filename)
{
	gchar* head = NULL;
	gint i = 0;
	const int max_cn = 5;
	while (i<= max_cn){
		head = tt_http_request(url);
		i ++;
		if(!head){
			continue;
		}
		if(!tt_is_lrc_buf(head)){
			g_free(head);
			head = NULL;
			continue;
		}
		break;
	}
	if(i> max_cn)
		return FALSE;
	gchar* buf =  g_strstrip(head);
	while(*buf){
		if(*buf=='[')
			break;
		buf++;
	}
	if(*buf){///buf is part of head,don't free
		buf = g_strdup(buf);
	}else
		buf = NULL;
	g_free(head);
///	lmp_debug("\n***\n%s\n*****", buf);

//	if(filename)
	FILE *fp = fopen(filename,"w");
	if(!fp){
		lmp_debug("fopen(%s):%s .",filename,strerror(errno));
		return FALSE;
	}
	fwrite(buf,strlen(buf),1,fp);
	fclose(fp);
	g_free(buf);
	return TRUE;
}


GSList* tt_parse_lyricslist(gchar* xml)
{
	lmp_debug("");
	xmlDoc* doc;
	xmlNode* root_node;
	xmlNode* cur_node;

	GSList* list = NULL;
	int i = 0;

	if(xml == NULL){
		lmp_debug("Get no XML .");
		return NULL;
	}

	doc = xmlReadDoc((const xmlChar *)xml, NULL, "UTF-8", 0);
	if(doc == NULL)
	{
		g_print("can't parse xml string\n");
		return NULL;
	}

	root_node = xmlDocGetRootElement(doc);
	if(root_node == NULL)
	{
		g_print("parse xml string failed\n");
		return NULL;
	}

	for(cur_node = root_node->children; cur_node; cur_node = cur_node->next)
	{
		LyricId* item = g_new0(LyricId, 1);
		item->no = i;
		gchar *id = (gchar*)xmlGetProp(cur_node,(const xmlChar *) "id");
		if(id == NULL) //FIXME: 为什么中间会有一个NULL元素
			continue;
		item->artist = (gchar*)xmlGetProp(cur_node,(const xmlChar *) "artist");
		item->title = (gchar*)xmlGetProp(cur_node, (const xmlChar *)"title");
		gchar* art_tit = g_strconcat(item->artist, item->title, NULL);
		item->url = g_strdup_printf(
		            "http://lrcct2.ttplayer.com/dll/lyricsvr.dll?dl?Id=%d&Code=%d&uid=01&mac=%012x",
		            atoi(id), 
		            tt_CodeFunc(atoi(id), art_tit), 
		            g_random_int_range(0, 0x7FFFFFFF));
//		tt_get_lyrics_content(item->url);
		g_free(art_tit);
		g_free(id);
		list = g_slist_append(list, item);
		++i;
	}

	xmlFreeDoc(doc);

	return list;
}

static void my_free(LyricId *item)
{
	if(!item){
		lmp_debug("come to where nerver should come .");
		return ;
	}
	g_free(item->url);
	g_free(item->artist);
	g_free(item->title);
	g_free(item);
}

void tt_free_list(GSList *list)
{
	if(!list){
		lmp_debug("Code mad !");
		return ;
	}
	g_slist_foreach(list,my_free,NULL);
	g_slist_free(list);
}

void print_list(GSList *l)
{
	if(!l){
		lmp_debug("I'm not god .");
		return ;
	}
	LyricId *item ;
	while(l){
		item = (LyricId *)l->data;
		g_print("%d,%s---%s,url:%s .\n",item->no,item->artist,item->title,item->url);
		l = l->next;
//		if(!l)tt_get_lyrics_content_save(item->url,NULL);
	}
}
